package com.zhanglu.authentication.service;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import com.zhanglu.authentication.entity.AuthUser;
import com.zhanglu.authentication.security.AuthenticationUser;
import com.zhanglu.authentication.security.TokenUtil;

import io.jsonwebtoken.ExpiredJwtException;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;

/**
 * @description
 * @Auther zhanglu
 * @Date 2017/11/30 下午4:54
 */
@Service
@Slf4j
public class TokenService {
    @Autowired
    private UserService    userService;
    @Autowired
    private RoleService    roleService;
    @Autowired
    private TokenUtil      tokenUtil;

    private ResponseEntity responseEntity = new ResponseEntity(HttpStatus.FORBIDDEN);

    public ResponseEntity registerToken(@NonNull String username, @NonNull String password) {
        AuthUser user = userService.getUserByUsername(username);
        if (Objects.isNull(user)) {
            log.warn("When registerToken,the username is {}, the user has no exist!", username);
            return responseEntity;
        }

        if (!password.equals(user.getPassword())) {
            log.warn("When registerToken,the username is {}, the password is wrong!", username);
            return responseEntity;
        }

        if (Objects.isNull(user.getStatus()) || user.getStatus().equals("INACTIVE")) {
            log.warn("When registerToken,the username is {}, the status is InActive!", username);
            return responseEntity;
        }

        HttpHeaders headers = new HttpHeaders();
        headers.add(tokenUtil.getCOOKIE_AUTH(), createToken(user, "create"));
        return new ResponseEntity(headers, HttpStatus.OK);
    }

    public ResponseEntity refreshToken(@NonNull String token) {
        if (Objects.isNull(token)) {
            log.warn("When refreshToken, token is null !");
            return responseEntity;
        }
        try {
            AuthenticationUser authenticationUser = tokenUtil.parserToken(token);
            if (Objects.isNull(authenticationUser)) {
                log.warn("When refreshToken, parserToken token result is null !");
                return responseEntity;
            }

            if (Objects.isNull(authenticationUser.getUsername())) {
                log.warn("When refreshToken, username is null ! The token is illegal");
                return responseEntity;
            }

            AuthUser user = userService.getUserByUsername(authenticationUser.getUsername());
            if (Objects.isNull(user)) {
                log.warn("When refreshToken,the username is {}, the user has no exist!", authenticationUser.getUsername());
                return responseEntity;
            }

            if (Objects.isNull(user.getStatus()) || user.getStatus().equals("INACTIVE")) {
                log.warn("When refreshToken,the username is {}, the status is InActive!", authenticationUser.getUsername());
                return responseEntity;
            }

            HttpHeaders headers = new HttpHeaders();
            headers.add(tokenUtil.getCOOKIE_AUTH(), createToken(user, "refresh"));
            return new ResponseEntity(headers, HttpStatus.OK);

        } catch (Exception e) {
            if (e instanceof ExpiredJwtException) { // 过期
                log.warn("the token is time out !");
                return new ResponseEntity(HttpStatus.REQUEST_TIMEOUT);
            }
            log.error("", e);
            return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    private String createToken(@NonNull AuthUser user, String type) {
        List<String> roles = roleService.selectRolesByUserId(user.getId());

        Calendar ca = Calendar.getInstance();
        ca.setTime(new Date());
        ca.add(Calendar.HOUR, 2);

        AuthenticationUser authenticationUser = new AuthenticationUser();
        BeanUtils.copyProperties(user, authenticationUser);
        authenticationUser.setExpireDate(ca.getTime());

        String token = tokenUtil.createJWT(authenticationUser, roles);
        log.info("{} {} token success,and token is {}", user.getUsername(), type, token);

        return token;
    }
}
